home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 May: Tool Chest / Developer CD Series May 1996 (Tool Chest) (Apple Computer) (1996).iso / Sample Code / SCSI Samples 1.0 / SCSI Simple Sample 06⁄15 ƒ / Src / DoSCSICommandWithSense.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-16  |  5.1 KB  |  173 lines  |  [TEXT/KAHL]

  1. /*                            DoScsiCommandWithSense.c                            */
  2. /*
  3.  * DoScsiCommandWithSense.c
  4.  * Copyright © 1992-93 Apple Computer Inc. All Rights Reserved.
  5.  *
  6.  * This is the common entry to the original and asynchronous SCSI Manager calls:
  7.  * if the asynchronous SCSI Manager is present, it calls it. If not present, it
  8.  * calls the original SCSI Manager and executes Request Sense if necessary.
  9.  */
  10. #include "SCSISimpleSample.h"
  11.  
  12. void                            IssueRequestSense(
  13.         register ScsiCmdBlockPtr    scsiCmdBlockPtr
  14.     );
  15.  
  16.  
  17. /*
  18.  * Do one SCSI Command. If the device returns Check Condition, issue Request Sense
  19.  * (original SCSI Manager only) and interpret the sense data. The original SCSI
  20.  * command status is in SCB.status. If it is statusErr or scsiNonZeroStatus,
  21.  * the sense data is in SCB.sense and the Request Sense status is in
  22.  * SCB.requestSenseStatus.
  23.  */
  24. void
  25. DoSCSICommandWithSense(
  26.         register ScsiCmdBlockPtr    scsiCmdBlockPtr,
  27.         Boolean                    displayError,
  28.         Boolean                    enableAsynchSCSI
  29.     )
  30. {
  31.         unsigned short            cmdBlockLength;
  32.         unsigned short            scsiHandshake[handshakeDataLength];
  33.         
  34. #define SCB    (*scsiCmdBlockPtr)
  35.         
  36.         /*
  37.          * Store the LUN information in the command block - this is needed
  38.          * for devices that only examine the command block for LUN values.
  39.          * (On SCSI-II, the asynchronous SCSI Manager also includes the
  40.          * LUN in the identify message).
  41.          */
  42.         SCB.command.scsi[1] &= ~0xE0;
  43.         SCB.command.scsi[1] |= (SCB.scsiDevice.LUN & 0x03) << 5;
  44.         cmdBlockLength = SCSIGetCommandLength((Ptr) &SCB.command);
  45.         /*
  46.          * Try to call SCSI Manager 4.3, if it fails with unimpErr, call
  47.          * the old SCSI Manager. Note: AsyncSCSI [in this instance]
  48.          * is synchronous. Real-world applications would use an asynchronous
  49.          * variant.
  50.          */
  51.         if (enableAsynchSCSI == FALSE || gEnableNewSCSIManager == FALSE)
  52.             SCB.status = unimpErr;                    /* Always original SCSI    */
  53.         else {
  54.             /*
  55.              * If SCB.transferQuantum equals one, request a polled transfer.
  56.              * Otherwise, setup a simple "single block" handshake field.
  57.              */
  58.             if (SCB.transferQuantum != 1) {
  59.                 CLEAR(scsiHandshake);
  60.                 scsiHandshake[0] = SCB.transferQuantum;
  61.             }
  62.             SCB.status = AsyncSCSI(
  63.                         SCB.scsiDevice,                /* Bus/target/LUN        */
  64.                         &SCB.command,                /* The command            */
  65.                         cmdBlockLength,                /* Command length        */
  66.                         SCB.writeToDevice,            /* TRUE if writing        */
  67.                         SCB.bufferPtr,                /* Data buffer, if any    */
  68.                         SCB.transferSize,            /* Data transfer length    */
  69.                         (SCB.transferQuantum == 1) ? NULL : scsiHandshake,
  70.                         &SCB.sense,                    /* For sense result        */
  71.                         sizeof SCB.sense,            /* Sense buffer size    */
  72.                         kScsiSpinUpCompletionTime,    /* Watchdog timeout        */
  73.                         &SCB.statusByte,            /* Gets STS Phase byte    */
  74.                         &SCB.actualTransferCount    /* Bytes actually done    */
  75.                     );
  76.         }
  77.         if (SCB.status != unimpErr) {
  78.             /*
  79.              * The asynchronous SCSI Manager did something interesting.
  80.              */
  81.             switch (SCB.status) {
  82.             case noErr:
  83.                 break;
  84.             case scsiDeviceNotThere:
  85.             case scsiSelectTimeout:
  86.             case scsiBusInvalid:
  87.             case scsiTIDInvalid:
  88.                 /* These all mean "no such device" */
  89.                 break;
  90.             case statusErr:
  91.                 /*
  92.                  * Hmm. If the error is statusErr, the device returned
  93.                  * "Check Condition" and the SCSI Manager successfully
  94.                  * issued a Request Sense. We'll display the result of the
  95.                  * sense and update the spinUpState.
  96.                  */
  97.                 SCB.requestSenseStatus = noErr;
  98.                 if (displayError)
  99.                     ShowRequestSense(scsiCmdBlockPtr);
  100.                 break;
  101.             default:
  102.                 if (displayError)
  103.                     ShowStatusError(SCB.scsiDevice, SCB.status, &SCB.command);
  104.                 break;
  105.             }
  106.         }
  107.         else {
  108.             /*
  109.              * Call the original SCSI Manager.
  110.              */
  111.             SCB.status = OriginalSCSI(
  112.                         SCB.scsiDevice.targetID,
  113.                         &SCB.command,
  114.                         cmdBlockLength,
  115.                         SCB.writeToDevice,
  116.                         SCB.bufferPtr,
  117.                         SCB.transferSize,
  118.                         SCB.transferQuantum,
  119.                         kScsiSpinUpCompletionTime,
  120.                         &SCB.statusByte,
  121.                         &SCB.actualTransferCount
  122.                     );
  123.             if (SCB.status != noErr) {
  124.                 if (displayError)
  125.                     ShowStatusError(SCB.scsiDevice, SCB.status, &SCB.command);
  126.                 if (SCB.status == statusErr) {
  127.                     /*
  128.                      * Device returned "Check Condition."
  129.                      */
  130.                     IssueRequestSense(scsiCmdBlockPtr);
  131.                     if (displayError)
  132.                         ShowRequestSense(scsiCmdBlockPtr);
  133.                 }
  134.             }
  135.         }
  136. }
  137.  
  138. /*
  139.  * Execute "Get Extended Sense." This should not fail. This is only called by
  140.  * "old" SCSI Manager calls: the new SCSI Manager always enables "autosense."
  141.  */
  142. void
  143. IssueRequestSense(
  144.         register ScsiCmdBlockPtr    scsiCmdBlockPtr
  145.     )
  146. {
  147.         SCSI_6_Byte_Command        requestSense;
  148.         unsigned short            statusByte;                /* <- From Status Phase    */
  149.         unsigned long            actualTransferCount;
  150.         
  151.         CLEAR(requestSense);
  152.         requestSense.opcode = kScsiCmdRequestSense;
  153.         requestSense.len = sizeof SCB.sense;
  154.         /*
  155.          * Stuff the logical unit number into the command block.
  156.          */
  157.         requestSense.lbn3 &= 0xE0;
  158.         requestSense.lbn3 |= (SCB.scsiDevice.targetID & 0x03) << 5;
  159.         SCB.requestSenseStatus = OriginalSCSI(
  160.                     SCB.scsiDevice.targetID,
  161.                     (SCSI_CommandPtr) &requestSense,
  162.                     sizeof requestSense,
  163.                     FALSE,                                /* No write                */
  164.                     (Ptr) &SCB.sense,
  165.                     sizeof SCB.sense,
  166.                     1,
  167.                     kScsiSpinUpCompletionTime,
  168.                     &statusByte,
  169.                     &actualTransferCount
  170.                 );
  171. }
  172.  
  173.